package com.zl.learning.thread.completable_future;

import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

public class CompletableFutureTest2 {
    private static final Random random = new Random();

    private static void sleep(int second) {
        try {
            TimeUnit.SECONDS.sleep(second);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static void sleep() {
        sleep(3);
    }

    private static CompletableFuture<String> getCompletableFuture(String val) {
        return CompletableFuture.supplyAsync(() -> getDealyString(val));
    }

    private static String getDealyString(String val) {
        int time = random.nextInt(5);
        sleep(time);
        String str = "Hello:" + val + "  const:" + time;
        System.out.println(str);
        return str;
    }

    public static class Test1 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            //第一种方式
            FutureTask<Integer> task = new FutureTask<>(() -> new Random().nextInt());
            new Thread(task).start();
            System.out.println("result: " + task.get());
            //第二种方方式
            ExecutorService executor = Executors.newCachedThreadPool(r -> {
                Thread t = new Thread(r, "MyThread");
                t.setDaemon(true);
                return t;
            });
            FutureTask<Integer> task2 = new FutureTask<>(() -> new Random().nextInt());
            executor.submit(task2);
            System.out.println("result2: " + task2.get());
        }
    }

    //变换结果
    public static class Test2 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            String result = CompletableFuture.supplyAsync(() -> {
                System.out.println(1);
                sleep();
                System.out.println("Hello ");
                return "Hello ";
            }).thenApplyAsync(v -> {
                System.out.println(2);
                sleep();
                System.out.println("world");
                return v + "world";
            }).get();
            System.out.println(result);
        }
    }

    //消费结果
    public static class Test3 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            CompletableFuture.supplyAsync(() -> {
                System.out.println(1);
                sleep();
                System.out.println("Hello ");
                return "Hello ";
            }).thenAccept(v -> {
                System.out.println(2);
                sleep();
                System.out.println(v + "world");
            }).get();
        }
    }

    //结合两个CompletionStage的结果，进行转化后返回
    public static class Test4 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            String result = CompletableFuture.supplyAsync(() -> {
                System.out.println(1);
                sleep();
                System.out.println("Hello ");
                return "Hello ";
            }).thenCombine(CompletableFuture.supplyAsync(() -> {
                System.out.println(2);
                sleep();
                System.out.println("world");
                return "world";
            }), (s1, s2) -> s1 + " " + s2).get();
            System.out.println(result);
        }
    }

    //两个CompletionStage，谁计算的快，就用那个CompletionStage的结果进行下一步的处理
    public static class Test5 {
        public static void main(String[] args) {

            CompletableFuture.supplyAsync(() -> {
                sleep(2);
                return "Hi Boy";
            }).acceptEitherAsync(CompletableFuture.supplyAsync(() -> {
                sleep(1);
                return "Hi Girl";
            }), s -> System.out.println(s)).join();
//            System.out.println(result);
        }
    }

    //运行时出现了异常，可以通过exceptionally进行补偿
    public static class Test6 {
        public static void main(String[] args) {

            String result = CompletableFuture.supplyAsync(() -> {
                sleep(2);
                return "Hi Boy";
            }).applyToEither(CompletableFuture.supplyAsync(() -> {
                sleep(1);
                if (true) {
                    throw new RuntimeException("HHHH");
                }
                return "Hi Girl";
            }), (s) -> {
                return s;
            }).exceptionally(e -> e.getMessage()).join();
            System.out.println(result);
        }
    }

    public static class Test7 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            CompletableFuture.allOf(getCompletableFuture("zhangsan"), getCompletableFuture("lisi"), getCompletableFuture("wangwu"), getCompletableFuture("zhaoliu"))
                    .thenAccept(new Consumer<Void>() {
                        @Override
                        public void accept(Void aVoid) {

                        }
                    }).get();
            CompletableFuture.allOf(getCompletableFuture("zhangsan"), getCompletableFuture("lisi"), getCompletableFuture("wangwu"), getCompletableFuture("zhaoliu"))
                    .thenAcceptAsync((r) -> {
                        System.out.println(r);
                    }).get();
            System.out.println("-------------------------------------------");
            CompletableFuture.anyOf(getCompletableFuture("zhangsan"), getCompletableFuture("lisi"), getCompletableFuture("wangwu"), getCompletableFuture("zhaoliu"))
                    .thenAcceptAsync(r -> System.out.println(r)).get();

//            System.out.println("aaaaaaaaaa");
        }

    }

    public static class Test8 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Long start = System.currentTimeMillis();
            List<CompletableFuture<String>> res = Arrays.asList(getCompletableFuture("zhangsan"), getCompletableFuture("lisi"), getCompletableFuture("wangwu"), getCompletableFuture("zhaoliu"));
            String result = res.stream().map(CompletableFuture::join).collect(Collectors.joining(","));
            System.out.println(result);
            Long end = System.currentTimeMillis();
            System.out.println("const:" + (end - start));
        }
    }

    public static class Test9 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Long start = System.currentTimeMillis();
            String res = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu").parallelStream().map(CompletableFutureTest2::getDealyString).collect(Collectors.joining(","));
            System.out.println(res);
            Long end = System.currentTimeMillis();
            System.out.println("const:" + (end - start));
        }
    }

    public static class Test10 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Long start = System.currentTimeMillis();
            List<CompletableFuture<String>> res = Arrays.asList(getCompletableFuture("zhangsan"), getCompletableFuture("lisi"), getCompletableFuture("wangwu"), getCompletableFuture("zhaoliu"));
            String result = res.stream().map(CompletableFuture::join).findAny().get();
            System.out.println(result);
            Long end = System.currentTimeMillis();
            System.out.println("const:" + (end - start));
        }
    }
}
